<?php

/*
 * Edit by shengxin
 * Click nbfs://nbhost/SystemFileSystem/Templates/Scripting/PHPClass.php to edit this template
 */

namespace api\mall\controller;

use cmf\controller\RestBaseController;
use api\mall\model\DailyTaskModel;
use api\mall\model\TaskLifelongModel;
use api\mall\model\TaskConfigModel;
use api\portal\model\UserModel;
use api\mall\model\MedalModel;
use api\mall\model\MedalUserModel;
use api\user\model\UserScoreLogModel;

/**
 * @OA\Tag(
 *     name="mall-task",
 *     description="任务系统"
 * )
 * @author PC
 */
class TaskController extends RestBaseController{
    
    public function __construct(\think\App $app = null) {
        parent::__construct($app);
        if(empty($this->user)){
            $this->error('login');
        }
        online_record($this->userId);
    }
    
    private function last_monday(){
        $week = date('w');
        if($week==1){
            //如果今天是周一,那么直接返回今天.
            return date('Y-m-d');
        }
        $last = date('Y-m-d',strtotime('last Monday'));
        return $last;
    }
    
    /**
     * 获取每天签到的奖励配置
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/get_login_config",
     *     summary="获取每天签到的奖励配置",
     *     security={{ "Bearer":{} }},
     * @OA\Parameter(
     *     ),
     *     @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function get_login_config(){
        $cfg =  cmf_get_option('mall_sign_in');
        if(empty($cfg)){
            $cfg = [1,1,1,1,1,1,1];
            cmf_set_option('mall_sign_in', $cfg);
        }
        $this->success('ok',$cfg);
    }
    
    /**
     * 获取签到记录,给一周的数据
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/login_task",
     *     summary="获取用户的签到记录",
     *     security={{ "Bearer":{} }},
     * @OA\Parameter(
     *     ),
     *     @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function login_task(){
        $model = new DailyTaskModel();
        $today = date('Y-m-d');
        $last_monday = $this->last_monday();
        $data = $model->field('date,status_i,task_data,task_key')->where('user_id',$this->userId)->where('task_key','SignInTask')->where('date','>=',$last_monday)->select();
        $map = [];
        foreach ($data as $day){
            $map[$day['date']] = $day;
        }
        if(!isset($map[$today])){
            $data = ['user_id'=>$this->userId,'date'=>$today,'status_i'=>1,'task_key'=>'SignInTask'];
            $model->insert($data);
            $map[$today] = $data;
        }
        $this->success($today,$map);
    }
    /**
     * 补签.补偿一次签到,必须是本周之内的一天,一周只能补签一次,task_data =1 表示是补签过的.
     * @OA\Post(
     *     tags={"mall-task"},
     *     path="/mall/task/compensate",
     *     summary="补签",
     *     security={{ "Bearer":{} }},
     *     @OA\RequestBody(
     *          @OA\JsonContent(
     *          type="object",
     *          @OA\Property(property="date",type="string",example="补签日期:2024-03-30")
     *          )    
     *     ),
     *     @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function compensate(){
        $date = $this->request->post('date');
//        if(empty($date)){
//            $this->error('日期不存在');
//        }
        $vd = validate('',['date'=>'日期格式不对'],false,false);
        $rs = $vd->rule('date','require|date')->check(['date'=>$date]);
        if(!$rs){
            $this->error('error:'.$vd->getError());
        }
        $date = date('Y-m-d',strtotime($date));
        $today = date('Y-m-d');
        if($date >= $today){
            $this->error('错误的日期:'.$date);
        }
        $last_monday = $this->last_monday();
        if($date<$last_monday){
            $this->error('不是本周的日期:'.$date);
        }
        $model = new DailyTaskModel();
        $sum = $model->where('user_id',$this->userId)->where('task_key','SignInTask')->where('date','>=',$last_monday)->sum('task_data');
        if($sum>0){
            $this->error('本周已经补签过了');
        }
        $date_data =$model->where('user_id',$this->userId)->where('task_key','SignInTask')->where('date',$date)->find();
        if($date_data && $date_data->status_i == 2){
            $this->error('已经领取过了');
        }
        if(empty($date_data)){
            $model->insert(['user_id'=>$this->userId,'task_key'=>'SignInTask','date'=>$date,'status_i'=>2,'task_data'=>1]);
        }else{
            $model->where('id',$date_data->id)->update(['status_i'=>2,'task_data'=>1]);
        }
        $instance = new \api\mall\task\SignInTask('SignInTask');
        $reward = $instance->calcReward($date);
        //奖励上限
        $valve = cmf_get_option('mall_task_valve');
        if($valve && isset($valve['max']) && $valve['max']>0){
            $max = $valve['max'];
            $sumModel = new UserScoreLogModel();
            $sum = $sumModel->where('type','task')->field('sum(score) sum_score,sum(coin) sum_coin')->find();
            if($sum['sum_score']+$sum['sum_coin']+$reward >= $max){
                $this->error(['code'=>999,'msg'=>'领取失败，系统已暂停发放']);
            }
        }
        
        
        $instance->get_reward($this->userId, $date);
        $umodel = new Usermodel();
        $user = $umodel->where('id',$this->userId)->field('coin,score,balance')->find();
        $this->success('补签成功',['user'=>$user->toArray(),'score'=>$reward]);
    }
    
    /**
     * 获取日常任务
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/daily_task",
     *     summary="获取日常任务,任务是否完成,是否领奖",
     *     security={{ "Bearer":{} }},

     *     @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */    
    public function daily_task(){
        $user_id = $this->userId;
        $model = new DailyTaskModel();
        $date = date('Y-m-d');
        $tasks = $model->where('user_id',$user_id)->where('date',$date)->select();
        $task_config = $this->get_taskconfig();
        $rs = [];
        //找出所有的今天任务
        //找出所有今天没有完成的任务,然后检测任务时候完成
        foreach ($task_config as $cfg){
            $comp = false;
            $task_key = $cfg['task_key'];
            $data = ['task_key'=>$task_key,'task_name'=>$cfg['task_name'],'status_i'=>0,'date'=>$date,'user_id'=>$user_id,'task_data'=>0,'task_reward'=>$cfg['task_reward'],'task_desc'=>$cfg['task_desc'],'task_req'=>$cfg['task_req']];
            $this_task = $data;
            foreach ($tasks as $task){
                //找到任务,并且已经完成
                if($task['task_key'] ==$task_key){
                    $comp = $task['status_i']>0;
                    $data['status_i'] = $task['status_i'];
                    $data['task_data'] = $task['task_data'];
                    $this_task = $task;
                    break;
                }
            }
            //没有完成的任务,检测任务是否完成
            $this_task['task_req'] = $cfg['task_req'];
            if(!$comp){
                $class = 'api\\mall\\task\\'.$task_key;
                $instance = new $class($task_key);
                $classArg = [$instance,'check_comp'];
                if(call_user_func($classArg,$this_task)){
                    $data['status_i'] = 1;
                    if(isset($this_task['id'])){
                        $model->where('id',$this_task['id'])->update(['status_i'=>1,'task_data'=>$data['task_data']]);
                    }else{
                        $newData = ['user_id'=>$user_id,'task_data'=>$data['task_data'],'status_i'=>1,'date'=>$date,'task_key'=>$task_key];
                        $model->insert($newData);    
                    }
                }
            }
            $rs[] = $data;
        }
        $this->success('ok',$rs);
    }
    
    private function get_taskconfig(){
        $taskModel = new TaskConfigModel();
        $cfgs = $taskModel->where('task_type',1)->select();
        $map = [];
        foreach ($cfgs as $cfg){
            $map[$cfg['task_key']] = $cfg;
        }
        return $map;
//        [
//            'online'=>['class'=>'OnlineTask','name'=>'在线时长','reward'=>1,'desc'=>'每日累积在线时长超过5分钟,获得1个星链石'],
//            'sign_in'=>['class'=>'SignInTask','name'=>'每日签到','reward'=>1,'desc'=>'每日签到,获得1个星链石'],
//            'talk_pub'=>['class'=>'TalkAllTask','name'=>'文明发言','reward'=>1,'desc'=>'每日在公共频道成功发送1条消息,获得1个星链石'],
//            'talk_pri'=>['class'=>'TalkTask','name'=>'文明私聊','reward'=>1,'desc'=>'每日跟好友私聊3句号,获得1个星链石'],
//            'curiosity'=>['class'=>'CuriosityTask','name'=>'好奇宝宝','reward'=>1,'desc'=>'每日在在美容院/数藏商城/零售区/文旅区/社交城均停留5秒,获得1个星链石'],
//            ];
    }
    
     /**
     * 领取任务奖励
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/get_reward",
     *     summary="领取任务奖励",
     *     security={{ "Bearer":{} }},
     * @OA\Parameter(
     *         name="task_key",
     *         @OA\Schema(
     *             type="string",
     *             format="str"
     *         ),
     *         in="query",
     *         description="任务ID",
     *         example="online",
     *         required=true,
     *     ),
     *     @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */   
    public function get_reward(){
        $task_key = $this->request->get('task_key');
        if(empty($task_key)){
            $this->error('任务ID去哪了?');
        }
        $date = date('Y-m-d');
        $model = new DailyTaskModel();
        $task = $model->where('user_id',$this->userId)->where('task_key',$task_key)->where('date',$date)->find();
        if(empty($task)){
            $this->error('奖励不存在');
        }
        if($task->status_i!=1){
            $this->error('奖励已领取');
        }
        $cfgs = $this->get_taskconfig();
        if(!isset($cfgs[$task_key])){
            $this->error('任务不存在');
        }
        $cfg = $cfgs[$task_key];
        $reward = $cfg['task_reward'];
        if(is_array($reward) && isset($reward['score'])){
            $reward = $reward['score'];
        }
        //奖励上限
        $valve = cmf_get_option('mall_task_valve');
        if($valve && isset($valve['max']) && $valve['max']>0){
            $max = $valve['max'];
            $sumModel = new UserScoreLogModel();
            $sum = $sumModel->where('type','task')->field('sum(score) sum_score,sum(coin) sum_coin')->find();
            if($sum['sum_score']+$sum['sum_coin']+$reward >= $max){
                $this->error(['code'=>999,'msg'=>'领取失败，系统已暂停发放']);
            }
        }
        
        //标记奖励已经领取
        $model->where('id',$task->id)->update(['status_i'=>2]);
        
        
        
        $class = 'api\\mall\\task\\'.$task_key;
        $instance = new $class($task_key);
        if($instance->get_reward($this->userId,$cfg)){
//            $data['status_i'] = 1;
//            $model->insert($data);    
        }
        $umodel = new Usermodel();
        $user = $umodel->where('id',$this->userId)->field('coin,score,balance')->find();
        $this->success('ok',['user'=>$user->toArray(),'score'=>$instance->reward]);
    }
    
   
    
    
    /**
     * 用户每天进入到数藏商城内景2、美容院内景4、零售区内景8、文旅沙盘16和社交沙盘32, 在场景中停留了5秒时发送数据
     * 任务数据会以 二进制形式保存 ,例如:bin 111110 = 62 ,火力全开,任务完成 
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/push_curiosity",
     *     summary="添加任务数据,好奇宝宝",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *         name="scence",
     *         @OA\Schema(
     *             type="integer",
     *             format="int32"
     *         ),
     *         in="post",
     *         description="场景ID",
     *         example=1,
     *         required=true
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function push_curiosity(){
        $scence = $this->request->post('scence/d',0);
        if($scence<1 || $scence>32){
            $this->error('未知的场景ID,1-32');
        }
        $model = new DailyTaskModel();
        $today = date('Y-m-d');
        $task = $model->where('user_id',$this->userId)->where('task_key','CuriosityTask')->where('date',$today)->find();
        $value = $scence;
        if($task){
            $value = $task->task_data|$value;
            $model->where('id',$task->id)->update(['task_data'=>$value]);
        }else{
            $save = ['user_id'=>$this->userId,'task_key'=>'CuriosityTask','date'=>$today,'task_data'=>$value];
            $model->insert($save);
        }
        $this->success('ok',$value);
    }
    
    /**
     * 用户需要完成任务文明发言,需要在世界聊天发3句话,没发言一次,告诉服务器一次,返回值表示今日发言次数,到达3次之后无需再发
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/push_world_talk",
     *     summary="添加任务数据,文明发言",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function push_world_talk(){
        $model = new DailyTaskModel();
        $today = date('Y-m-d');
        $task = $model->where('user_id',$this->userId)->where('task_key','TalkAllTask')->where('date',$today)->find();
        $task_data = 1;
        if(empty($task)){
            $task = ['user_id'=>$this->userId,'task_key'=>'TalkAllTask','date'=>$today,'task_data'=>1];
            $model->insert($task);
        }else{
            $task_data = $task->task_data+1;
            $model->where('id',$task->id)->setInc('task_data',1);
        }
        $this->success('ok',$task_data);
    }
    
    
    
    /**
     * 获取推广任务,检测推广任务是否完成
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/promote_task",
     *     summary="获取推广任务数据",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function promote_task(){
        return $this->_get_task(2);
    }
    //----------------------------------------------------------------------------------------------
    //以下成长任务
    //**********************************************************************************************
    
    /**
     * 获取成长任务,检测成长任务是否完成
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/lifelong_task",
     *     summary="获取成长任务数据",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function lifelong_task(){
        return $this->_get_task(0);
    }
    
    private function _get_task($type){
        $taskModel = new TaskConfigModel();
        $user_id = $this->userId;
        $cfgs = $taskModel->where('task_type',$type)->select();
        $lifelongModel = new TaskLifelongModel();
        $mytasks = $lifelongModel->where('user_id',$user_id)->select();
        $checkers = [];
        foreach ($cfgs as $tkey=>$cfg){
            $id = $cfg['id'];
            $cfg['status_i'] = 0;
            $cfg['task_data'] = $cfg['task_req'];
            $comp = false;
            foreach ($mytasks as $task){
                if($task['task_id'] == $id){
                    $comp = true;
                    //变成个人数据
                    $cfg['id'] = $task['id'];
                    $cfg['status_i'] = $task['status_i'];
                    break;
                }
            }
            //任务没有完成,检测是否完成
            if(!$comp){
                $key = $cfg['task_key'];
                if(empty($checkers[$key])){
                    $class = 'api\\mall\\task\\'.$key;
                    $checker = new $class($cfg);
                }else{
                    $checker = $checkers[$key];
                }
                //检测完成任务
                if($checker->check_comp($this->user)){
                    $taskData = [
                        'user_id'=>$user_id,'task_id'=>$id,'status_i'=>1,'create_time'=>time(),'task_key'=>$key
                    ];
                    $cfg['status_i'] = 1;
                    $lifelongModel->insert($taskData);
                }
                $cfg['task_data'] = $checker->task_data;
            }
            $cfgs[$tkey] = $cfg;
        }
        $this->success('ok',$cfgs);
    }
    /**
     * 领取成长/推广任务奖励
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/lifelong_reward",
     *     summary="领取成长/推广任务奖励",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *          name="id",
     *         @OA\Schema(
     *             type="integer",
     *             format="int32"
     *         ),
     *         in="get",
     *         description="任务ID",
     *         example=1,
     *         required=true
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function lifelong_reward(){
        
        $task_id = $this->request->get('id');
        $uTaskModel = new TaskLifelongModel();
        $task = $uTaskModel->where('id',$task_id)->find();
        if(empty($task)){
            $this->error('奖励不存在');
        }
        if($task->user_id!=$this->userId){
            $this->error('奖励不属于你');
        }
        if($task->status_i!==1){
            $this->error('奖励不能领取:'.$task->status_i);
        }
        $cfgModel = new TaskConfigModel();
        $cfg = $cfgModel->where('id',$task['task_id'])->find();
        if($cfg['task_type']==2){
            $model = new \app\portal\model\UserRealNameInfoModel();
            $exist = $model->where('user_id',$this->userId)->find();
            if(!$exist){
                $this->error(['code'=>998,'msg'=>'还未实名验证,请先完成实名认证']);
            }
        }
        $reward = $cfg['task_reward'];
        
        $valve = cmf_get_option('mall_task_valve');
        if($valve && isset($valve['max']) && $valve['max']>0){
            $max = $valve['max'];
            $sumModel = new UserScoreLogModel();
            $sum = $sumModel->where('type','task')->field('sum(score) sum_score,sum(coin) sum_coin')->find();
            if($sum['sum_score']+$sum['sum_coin']+$reward >= $max){
                $this->error(['code'=>999,'msg'=>'领取失败，系统已暂停发放']);
            }
        }
        
        $data = ['score'=>$reward];
        //add reward
        $userModel = new UserModel();
        $userModel->add_score($this->userId, $reward, '完成成长任务领取奖励:'.$cfg['task_name'],'task');
        while($cfg['task_medal']>0){
            $medalModel = new MedalModel();
            $medal = $medalModel->where('id',$cfg['task_medal'])->find();
            if(empty($medal)){
                break;
            }
            $userMedalModel = new MedalUserModel();
            $exist = $userMedalModel->where('user_id',$this->userId)->where('medal_id',$cfg['task_medal'])->find();
            if($exist){
                break;
            }
            
            $data['medal'] = $medal->toArray();
            $data['medal']['medal_url'] = cmf_get_image_url($medal->medal_url);
            $userMedalModel->insert(['user_id'=>$this->userId,'medal_id'=>$cfg['task_medal'],'status_i'=>0,'create_time'=> time()]);
            break;
        }
        $uTaskModel->where('id',$task_id)->update(['status_i'=>2]);
        $userModel->addTaskLog($this->userId, $reward, '完成成长任务领取奖励:'.$cfg['task_name']);
        $user = $userModel->where('id',$this->userId)->field('coin,score,balance')->find();
        $data['user'] = $user->toArray();
        $this->success('ok',$data);
        
    }
    
    /**
     * 获取勋章数据,所有勋章,和指定用户已经获得的勋章
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/medals",
     *     summary="获取勋章数据",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *         name="uid",
     *         @OA\Schema(
     *             type="int",
     *             format="str"
     *         ),
     *         in="query",
     *         description="用户ID",
     *         example="online",
     *         required=true, 
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function medals(){
        $model = new MedalModel();
        $all = $model->field('id,medal_name,medal_key,medal_desc,medal_url')->select();
        $list = [];
        foreach ($all as $m){
            $m['medal_url'] = cmf_get_image_url($m['medal_url']);
            $list[] = $m;
        }
        $uid = $this->request->get('uid/d',0);
        if($uid<1){
            $uid = $this->userId;
        }
        $umodel = new MedalUserModel();
        $mylist = $umodel->where('user_id',$uid)->field('medal_id,status_i')->select();
        $data = ['medals'=>$list,'mymedal'=>$mylist];
        $this->success('ok',$data);
    }
    /**
     * 获取指定用户已经获得的勋章
     * @OA\Get(
     *     tags={"mall-task"},
     *     path="/mall/task/user_medals",
     *     summary="获取指定用户已经获得的勋章",
     *     security={{ "Bearer":{} }},
     *     @OA\Parameter(
     *         name="uid",
     *         @OA\Schema(
     *             type="int",
     *             format="str"
     *         ),
     *         in="query",
     *         description="用户ID",
     *         example="online",
     *         required=true, 
     *     ),
     * @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function user_medals(){
        $umodel = new MedalUserModel();
        $userid = $this->request->get('uid/d',0);
        if($userid<1){
            $userid=$this->userId;
        }
        $mylist = $umodel->where('user_id',$userid)->field('medal_id,status_i')->select();
        $this->success('ok',$mylist);
    }
    
    /**
     * 佩戴勋章,传入勋章ID即可
     * @OA\Post(
     *     tags={"mall-task"},
     *     path="/mall/task/wear_medal",
     *     summary="佩戴勋章",
     *     security={{ "Bearer":{} }},
     *     @OA\RequestBody(
     *          @OA\JsonContent(
     *          type="object",
     *          @OA\Property(property="id",type="integer",example="勋章ID")
     *          )    
     *     ),
     *     @OA\Response(response=200, ref="#/components/responses/200")
     * )
     */
    public function wear_medal(){
        $id = $this->request->post('id/d',0);
        if(empty($id)){
            $this->error('勋章ID呢');
        }
        $medalM = new MedalModel();
        $medal = $medalM->where('id',$id)->find();
        if(empty($medal)){
            $this->error('勋章ID无效');
        }
        $userModel = new UserModel();
        $userModel->where('id',$this->userId)->update(['medal_url'=> cmf_get_image_url($medal['medal_url'])]);
        $umodel = new MedalUserModel();
        $umodel->where('user_id',$this->userId)->where('status_i',1)->update(['status_i'=>0]);
        $umodel->where('user_id',$this->userId)->where('medal_id',$id)->update(['status_i'=>1]);
        $mylist = $umodel->where('user_id',$this->userId)->field('medal_id,status_i')->select();
        $data = ['mymedal'=>$mylist];
        $this->success('ok',$data);
    }

}
